# frozen_string_literal: true

require_relative '../unit_helper'

module Watir
  module Locators
    class Row
      describe SelectorBuilder do
        include LocatorSpecHelper

        let(:row_selector_builder) { described_class.new(attributes, query_scope) }
        let(:selector_built) { row_selector_builder.build(selector).reject { |key| key == :scope } }
        let(:selector) { @selector || {} }

        describe '#build' do
          context 'with query scopes' do
            it 'with only table query scope' do
              @query_scope = element(tag_name: 'table')

              built = {xpath: "./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
                              "./*[local-name()='thead']/*[local-name()='tr'] | " \
                              "./*[local-name()='tfoot']/*[local-name()='tr']"}

              expect(selector_built).to eq built
            end

            it 'with tbody query scope' do
              @query_scope = element(tag_name: 'tbody')
              built = {xpath: "./*[local-name()='tr']"}

              expect(selector_built).to eq built
            end

            it 'with thead query scope' do
              @query_scope = element(tag_name: 'thead')
              built = {xpath: "./*[local-name()='tr']"}

              expect(selector_built).to eq built
            end

            it 'with tfoot query scope' do
              @query_scope = element(tag_name: 'tfoot')
              built = {xpath: "./*[local-name()='tr']"}

              expect(selector_built).to eq built
            end
          end

          context 'when tag name is specified' do
            before do
              @query_scope = element(tag_name: 'table')
            end

            context 'when index' do
              it 'positive' do
                @selector = {index: 1}
                built = {xpath: "(./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
                                "./*[local-name()='thead']/*[local-name()='tr'] | " \
                                "./*[local-name()='tfoot']/*[local-name()='tr'])[2]"}

                expect(selector_built).to eq built
              end

              it 'negative' do
                @selector = {index: -3}
                built = {xpath: "(./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
                                "./*[local-name()='thead']/*[local-name()='tr'] | " \
                                "./*[local-name()='tfoot']/*[local-name()='tr'])[last()-2]"}

                expect(selector_built).to eq built
              end

              it 'last' do
                @selector = {index: -1}
                built = {xpath: "(./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
                                "./*[local-name()='thead']/*[local-name()='tr'] | " \
                                "./*[local-name()='tfoot']/*[local-name()='tr'])[last()]"}

                expect(selector_built).to eq built
              end

              it 'does not return index if it is zero' do
                @selector = {index: 0}
                built = {xpath: "./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
                                "./*[local-name()='thead']/*[local-name()='tr'] | " \
                                "./*[local-name()='tfoot']/*[local-name()='tr']"}

                expect(selector_built).to eq built
              end

              it 'raises exception when index is not an Integer', :skip_after do
                @selector = {index: 'foo'}
                msg = /expected one of \[(Integer|Fixnum)\], got "foo":String/
                expect { selector_built }.to raise_exception TypeError, msg
              end
            end

            context 'when multiple locators' do
              it 'attribute and class' do
                @selector = {id: 'gregory', class: /brick/}
                built = {xpath: "./*[local-name()='tr'][contains(@class, \"brick\")][@id='gregory'] | " \
                                "./*[local-name()='tbody']/*[local-name()='tr']" \
                                "[contains(@class, \"brick\")][@id='gregory'] | " \
                                "./*[local-name()='thead']/*[local-name()='tr']" \
                                "[contains(@class, \"brick\")][@id='gregory'] | " \
                                "./*[local-name()='tfoot']/*[local-name()='tr']" \
                                "[contains(@class, \"brick\")][@id='gregory']"}

                expect(selector_built).to eq built
              end
            end

            context 'when a text value' do
              it 'returns locators that can not be directly translated' do
                @selector = {text: 'Gregory'}
                built = {xpath: "./*[local-name()='tr'] | ./*[local-name()='tbody']/*[local-name()='tr'] | " \
                                "./*[local-name()='thead']/*[local-name()='tr'] | " \
                                "./*[local-name()='tfoot']/*[local-name()='tr']", text: 'Gregory'}

                expect(selector_built).to eq built
              end
            end
          end
        end
      end
    end
  end
end
